#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>

#define PORT 4321
#define BUFFER_SIZE 4096

int main() {
    int server_fd, client_fd;
    struct sockaddr_in address;
    int opt = 1;
    int addrlen = sizeof(address);
    
    // 创建socket文件描述符
    if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
        perror("socket failed");
        exit(EXIT_FAILURE);
    }
    
    // 设置socket选项
    if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) {
        perror("setsockopt");
        exit(EXIT_FAILURE);
    }
    
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;//inet_addr("192.168.11.220");
    address.sin_port = htons(PORT);
    
    // 绑定socket到指定IP和端口
    if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
        perror("bind failed");
        exit(EXIT_FAILURE);
    }
    
    printf("等待连接在端口 %d...\n", PORT);
    
    // 开始监听
    if (listen(server_fd, 3) < 0) {
        perror("listen");
        exit(EXIT_FAILURE);
    }
    
    // 接受客户端连接
    if ((client_fd = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) {
        perror("accept");
        exit(EXIT_FAILURE);
    }
    
    printf("连接来自: %s:%d\n", inet_ntoa(address.sin_addr), ntohs(address.sin_port));
    
    // 1. 接收文件名长度(4字节)
    uint32_t filename_size;
    if (recv(client_fd, &filename_size, sizeof(filename_size), 0) != sizeof(filename_size)) {
        perror("接收文件名长度失败");
        close(client_fd);
        exit(EXIT_FAILURE);
    }
    filename_size = ntohl(filename_size);
    printf("接收文件名大小: %u 字节\n", filename_size);
    
    // 2. 接收文件名
    char filename[256];
    if (recv(client_fd, filename, filename_size, 0) != filename_size) {
        perror("接收文件名失败");
        close(client_fd);
        exit(EXIT_FAILURE);
    }
    filename[filename_size] = '\0';
    printf("接收文件名: %s\n", filename);
    
    // 3. 接收文件大小(4字节)
    uint32_t file_size;
    if (recv(client_fd, &file_size, sizeof(file_size), 0) != sizeof(file_size)) {
        perror("接收文件大小失败");
        close(client_fd);
        exit(EXIT_FAILURE);
    }
    file_size = ntohl(file_size);
    printf("接收文件大小: %u 字节\n", file_size);
    
    // 4. 接收文件数据
    FILE *file = fopen(filename, "wb");
    if (!file) {
        perror("无法创建文件");
        close(client_fd);
        exit(EXIT_FAILURE);
    }
    
    char buffer[BUFFER_SIZE];
    uint32_t received = 0;
    while (received < file_size) {
        int bytes_to_read = (file_size - received) < BUFFER_SIZE ? (file_size - received) : BUFFER_SIZE;
        int bytes_read = recv(client_fd, buffer, bytes_to_read, 0);
        if (bytes_read <= 0) {
            perror("接收文件数据失败");
            break;
        }
        fwrite(buffer, 1, bytes_read, file);
        received += bytes_read;
        printf("已接收: %u/%u 字节\r", received, file_size);
    }
    
    printf("\n文件保存成功: %s\n", filename);
    
    fclose(file);
    close(client_fd);
    close(server_fd);
    
    return 0;
}
